home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/env python
-
- ## Printing troubleshooter
-
- ## Copyright (C) 2008 Red Hat, Inc.
- ## Copyright (C) 2008 Tim Waugh <twaugh@redhat.com>
-
- ## This program is free software; you can redistribute it and/or modify
- ## it under the terms of the GNU General Public License as published by
- ## the Free Software Foundation; either version 2 of the License, or
- ## (at your option) any later version.
-
- ## This program is distributed in the hope that it will be useful,
- ## but WITHOUT ANY WARRANTY; without even the implied warranty of
- ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ## GNU General Public License for more details.
-
- ## You should have received a copy of the GNU General Public License
- ## along with this program; if not, write to the Free Software
- ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- import gtk
- import pprint
- import sys
- import traceback
-
- if __name__ == "__main__":
- import os.path
- import gettext
- gettext.textdomain ('system-config-printer')
-
- if sys.argv[0][0] != '/':
- cwd = os.getcwd ()
- path = cwd + os.path.sep + sys.argv[0]
- else:
- path = sys.argv[0]
- sub = os.path.dirname (path)
- root = os.path.dirname (sub)
- sys.path.append (root)
-
- import base
- from base import *
-
- class Troubleshooter:
- def __init__ (self, quitfn=None, parent=None):
- self._in_module_call = False
-
- main = gtk.Window ()
- if parent:
- main.set_transient_for (parent)
- main.set_position (gtk.WIN_POS_CENTER_ON_PARENT)
- main.set_modal (True)
-
- main.set_title (_("Printing troubleshooter"))
- main.set_property ("default-width", 400)
- main.set_property ("default-height", 350)
- main.connect ("delete_event", self.quit)
- self.main = main
- self.quitfn = quitfn
-
- vbox = gtk.VBox ()
- main.add (vbox)
- ntbk = gtk.Notebook ()
- ntbk.set_border_width (6)
- vbox.pack_start (ntbk, True, True, 0)
- vbox.pack_start (gtk.HSeparator (), False, False, 0)
- box = gtk.HButtonBox ()
- box.set_border_width (6)
- box.set_spacing (3)
- box.set_layout (gtk.BUTTONBOX_END)
-
- back = gtk.Button (stock='gtk-go-back')
- back.connect ('clicked', self._on_back_clicked)
- back.set_sensitive (False)
- self.back = back
-
- close = gtk.Button (stock='gtk-close')
- close.connect ('clicked', self.quit)
- self.close = close
-
- cancel = gtk.Button (stock='gtk-cancel')
- cancel.connect ('clicked', self.quit)
- self.cancel = cancel
-
- forward = gtk.Button (stock='gtk-go-forward')
- forward.connect ('clicked', self._on_forward_clicked)
- forward.set_flags (gtk.CAN_DEFAULT | gtk.HAS_DEFAULT)
- self.forward = forward
-
- box.pack_start (back, False, False, 0)
- box.pack_start (cancel, False, False, 0)
- box.pack_start (close, False, False, 0)
- box.pack_start (forward, False, False, 0)
- vbox.pack_start (box, False, False, 0)
-
- ntbk.set_current_page (0)
- ntbk.set_show_tabs (False)
- self.ntbk = ntbk
- self.current_page = 0
-
- self.questions = []
- self.question_answers = []
- self.answers = {}
- self.moving_backwards = False
-
- main.show_all ()
-
- def quit (self, *args):
- if self._in_module_call:
- try:
- self.questions[self.current_page].cancel_operation ()
- except:
- self._report_traceback ()
-
- return
-
- try:
- self.questions[self.current_page].disconnect_signals ()
- except:
- self._report_traceback ()
-
- # Delete the questions so that their __del__ hooks can run.
- # Do this in reverse order of creation.
- for i in xrange (len (self.questions)):
- self.questions.pop ()
-
- self.main.hide ()
- if self.quitfn:
- self.quitfn (self)
-
- def get_window (self):
- # Any error dialogs etc from the modules need to be able
- # to set themselves transient for this window.
- return self.main
-
- def no_more_questions (self, question):
- page = self.questions.index (question)
- debugprint ("Page %d: No more questions." % page)
- self.questions = self.questions[:page + 1]
- self.question_answers = self.question_answers[:page + 1]
- for p in range (self.ntbk.get_n_pages () - 1, page, -1):
- self.ntbk.remove_page (p)
- self._set_back_forward_buttons ()
-
- def new_page (self, widget, question):
- page = len (self.questions)
- debugprint ("Page %d: new: %s" % (page, str (question)))
- self.questions.append (question)
- self.question_answers.append ([])
- self.ntbk.insert_page (widget, position=page)
- widget.show_all ()
- if page == 0:
- try:
- question.connect_signals (self._set_back_forward_buttons)
- except:
- self._report_traceback ()
-
- self.ntbk.set_current_page (page)
- self.current_page = page
- self._set_back_forward_buttons ()
- return page
-
- def is_moving_backwards (self):
- return self.moving_backwards
-
- def answers_as_text (self):
- text = ""
- n = 1
- for i in range (self.current_page):
- answers = self.question_answers[i].copy ()
- for hidden in filter (lambda x: x.startswith ("_"), answers.keys()):
- del answers[hidden]
- if len (answers.keys ()) == 0:
- continue
- text += "Page %d (%s):" % (n, self.questions[i]) + '\n'
- text += pprint.pformat (answers) + '\n'
- n += 1
- return text.rstrip () + '\n'
-
- def busy (self):
- self.forward.set_sensitive (False)
- self.back.set_sensitive (False)
- gdkwin = self.get_window ().window
- if gdkwin:
- gdkwin.set_cursor (gtk.gdk.Cursor (gtk.gdk.WATCH))
- while gtk.events_pending ():
- gtk.main_iteration ()
-
- def ready (self):
- gdkwin = self.get_window ().window
- if gdkwin:
- gdkwin.set_cursor (gtk.gdk.Cursor (gtk.gdk.LEFT_PTR))
-
- self._set_back_forward_buttons ()
-
- def _set_back_forward_buttons (self, *args):
- page = self.current_page
- self.back.set_sensitive (page != 0)
- if len (self.questions) == page + 1:
- # Out of questions.
- debugprint ("Out of questions")
- self.forward.set_sensitive (False)
- self.close.show ()
- self.cancel.hide ()
- else:
- can = self._can_click_forward (self.questions[page])
- debugprint ("Page %d: can click forward? %s" % (page, can))
- self.forward.set_sensitive (can)
- self.close.hide ()
- self.cancel.show ()
-
- def _on_back_clicked (self, widget):
- self.busy ()
- self.moving_backwards = True
- try:
- self.questions[self.current_page].disconnect_signals ()
- except:
- self._report_traceback ()
-
- self.current_page -= 1
- question = self.questions[self.current_page]
- while not self._display (question):
- # Skip this one.
- debugprint ("Page %d: skip" % (self.current_page))
- self.current_page -= 1
- question = self.questions[self.current_page]
-
- self.ntbk.set_current_page (self.current_page)
- answers = {}
- for i in range (self.current_page):
- answers.update (self.question_answers[i])
- self.answers = answers
-
- try:
- self.questions[self.current_page].\
- connect_signals (self._set_back_forward_buttons)
- except:
- self._report_traceback ()
-
- self.moving_backwards = False
- self.ready ()
-
- def _on_forward_clicked (self, widget):
- self.busy ()
- answer_dict = self._collect_answer (self.questions[self.current_page])
- self.question_answers[self.current_page] = answer_dict
- self.answers.update (answer_dict)
-
- try:
- self.questions[self.current_page].disconnect_signals ()
- except:
- self._report_traceback ()
-
- self.current_page += 1
- question = self.questions[self.current_page]
- while not self._display (question):
- # Skip this one, but collect its answers.
- answer_dict = self._collect_answer (question)
- self.question_answers[self.current_page] = answer_dict
- self.answers.update (answer_dict)
- debugprint ("Page %d: skip" % (self.current_page))
- self.current_page += 1
- question = self.questions[self.current_page]
-
- self.ntbk.set_current_page (self.current_page)
- try:
- question.connect_signals (self._set_back_forward_buttons)
- except:
- self._report_traceback ()
-
- self.ready ()
- if get_debugging ():
- self._dump_answers ()
-
- def _dump_answers (self):
- debugprint (self.answers_as_text ())
-
- def _report_traceback (self):
- print "Traceback:"
- (type, value, tb) = sys.exc_info ()
- tblast = traceback.extract_tb (tb, limit=None)
- if len (tblast):
- tblast = tblast[:len (tblast) - 1]
- extxt = traceback.format_exception_only (type, value)
- for line in traceback.format_tb(tb):
- print line.strip ()
- print extxt[0].strip ()
-
- def _display (self, question):
- result = False
- self._in_module_call = True
- try:
- result = question.display ()
- except:
- self._report_traceback ()
-
- self._in_module_call = False
- question.displayed = result
- return result
-
- def _can_click_forward (self, question):
- try:
- return question.can_click_forward ()
- except:
- self._report_traceback ()
- return True
-
- def _collect_answer (self, question):
- answer = {}
- self._in_module_call = True
- try:
- answer = question.collect_answer ()
- except:
- self._report_traceback ()
-
- self._in_module_call = False
- return answer
-
- QUESTIONS = ["Welcome",
- "SchedulerNotRunning",
- "CheckLocalServerPublishing",
- "ChoosePrinter",
- "CheckPrinterSanity",
- "CheckPPDSanity",
-
- "LocalOrRemote",
- "DeviceListed",
- "CheckUSBPermissions",
-
- "RemoteAddress",
- "CheckNetworkServerSanity",
- "ChooseNetworkPrinter",
-
- "NetworkCUPSPrinterShared",
-
- "QueueNotEnabled",
- "QueueRejectingJobs",
- "PrinterStateReasons",
-
- "ServerFirewalled",
- "ErrorLogCheckpoint",
- "PrintTestPage",
- "ErrorLogFetch",
- "PrinterStateReasons",
- "ErrorLogParse",
- "Locale",
- "Shrug"]
-
- def run (quitfn=None, parent=None):
- troubleshooter = Troubleshooter (quitfn, parent=parent)
- modules_imported = []
- for module in QUESTIONS:
- try:
- if not module in modules_imported:
- exec ("from %s import %s" % (module, module))
- modules_imported.append (module)
-
- exec ("%s (troubleshooter)" % module)
- except:
- troubleshooter._report_traceback ()
- return troubleshooter
-
- if __name__ == "__main__":
- import sys, getopt
- try:
- opts, args = getopt.gnu_getopt (sys.argv[1:], '',
- ['debug'])
- for opt, optarg in opts:
- if opt == '--debug':
- set_debugging (True)
- except getopt.GetoptError:
- pass
- gtk.gdk.threads_init()
- run (gtk.main_quit)
- gtk.gdk.threads_enter ()
- gtk.main ()
- gtk.gdk.threads_leave ()
-